package top.dreamix.njitkit.activities

import android.content.Intent
import android.net.CaptivePortal
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Build
import android.os.Bundle
import top.dreamix.njitkit.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewmodel.compose.viewModel
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.header
import io.ktor.http.URLBuilder
import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import top.dreamix.njitkit.data.network.Account
import top.dreamix.njitkit.ui.screen.CaptivePortalLoginUi
import top.dreamix.njitkit.ui.theme.NJITKitTheme
import top.dreamix.njitkit.ui.viewmodel.NetworkConfigViewModel
import top.dreamix.njitkit.util.NetworkUtil


class CaptivePortalLoginActivity : ComponentActivity() {
    var captivePortal: CaptivePortal? = null
    var network: Network? = null
    var connectivityManager: ConnectivityManager? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.info("Getting captive portal")
        connectivityManager = getSystemService<ConnectivityManager?>(ConnectivityManager::class.java)
        setupNetworkMonitoring()
//        this.mDpm = getSystemService<DevicePolicyManager?>(DevicePolicyManager::class.java)
//        this.mWifiManager = getSystemService<WifiManager?>(WifiManager::class.java)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            captivePortal = intent.getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL, CaptivePortal::class.java)
            network = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK, Network::class.java)
        } else {
            captivePortal = intent.getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL)
            network = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK)
        }
        // TODO 添加检测VPN功能（VPN和移动数据开启时，流量不能走指定网络，会导致检测功能失效）
        connectivityManager!!.bindProcessToNetwork(network)

        val newIntent = Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN)
            // SSL Problem
            .putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, intent.getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL))
            .putExtra("android.net.extra.CAPTIVE_PORTAL_USER_AGENT", intent.getStringExtra("android.net.extra.CAPTIVE_PORTAL_USER_AGENT"))
            .putExtra("android.net.extra.CAPTIVE_PORTAL", captivePortal!!)
        if (captivePortal == null) {
            Toast.makeText(this, "Captive Portal is null", Toast.LENGTH_SHORT).show()
            finish()
            return
        }
        enableEdgeToEdge()
        setContent {
            NJITKitTheme {
                val vm = viewModel<NetworkConfigViewModel>()
                val uiState by vm.uiState.collectAsState()

                CaptivePortalLoginUi(
                    finishActivity = this::finishAndRemoveTask,
                    ignoreNetwork = { /*captivePortal!!::ignoreNetwork*/ },
                    confirmNetwork = {
                        captivePortal!!.reportCaptivePortalDismissed()
                        connectivityManager!!.reportNetworkConnectivity(network, true)
                    },
                    uiState = uiState,
                    saveNetworkSetting = vm::saveNetworkSetting,
                    loginNetwork = this::loginNetwork,
                    intent = newIntent,
                    onAccountSelected = vm::selectAccount
                )
            }
        }
    }

    private val json = Json {
        ignoreUnknownKeys = true // 忽略未知字段
        isLenient = true // 宽松模式
        coerceInputValues = true // 允许类型强制转换
    }

    fun loginNetwork(account: Account, callback: (Boolean, String) -> Unit) {
        this.lifecycleScope.launch {
            try {
                // 根据运营商添加后缀
                val fullAccount = "${account.username}${account.operator.suffix}"

                // 构建请求URL
                val url = URLBuilder("http://172.31.255.156:801/eportal/portal/login").apply {
                    parameters.apply {
                        append("callback", "dr1004")
                        append("login_method", "1")
                        append("user_account", ",0,$fullAccount")
                        append("user_password", account.password)
                        append("wlan_user_ip", "")
                        append("wlan_user_ipv6", "")
                        append("wlan_user_mac", "000000000000")
                        append("wlan_ac_ip", "")
                        append("wlan_ac_name", "")
                        append("jsVersion", "4.2.2")
                        append("terminal_type", "1")
                        append("lang", "zh-cn")
                        append("v", "8707")
                    }
                }.build()

                // 使用全局 HttpClient 发送请求
                val responseText: String = NetworkUtil.httpClient.get(url) {
                    // 添加特定的请求头（部分头已经在默认配置中设置）
                    header("Referer", "http://172.31.255.156/")
                }.body()

                // 处理响应数据
                val jsonResponse = extractJson(responseText)
                val loginResponse = json.decodeFromString<LoginResponse>(jsonResponse)

                // 判断登录结果
                if (loginResponse.result == 0) {
                    callback(false, loginResponse.msg)
                } else {
                    callback(true, loginResponse.msg)
                }
            } catch (e: Exception) {
                callback(false, "network request failed: ${e.message}")
            }
        }
    }
    private fun extractJson(response: String): String {
        val startIndex = response.indexOf('{')
        val endIndex = response.lastIndexOf('}')
        return if (startIndex != -1 && endIndex != -1 && startIndex < endIndex) {
            response.substring(startIndex, endIndex + 1)
        } else {
            "{}"
        }
    }

    @Serializable
    data class LoginResponse(
        val result: Int,
        val msg: String,
        val ret_code: Int? = null
    )

    private fun setupNetworkMonitoring() {
        val networkCallback = object : ConnectivityManager.NetworkCallback() {
            override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
                // 检查是否是目标网络且已通过验证
                if (network == this@CaptivePortalLoginActivity.network &&
                    networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {

                    runOnUiThread {
                        finishAndRemoveTask()
                    }
                }
            }

            override fun onLost(network: Network) {
                if (network == this@CaptivePortalLoginActivity.network) {
                    runOnUiThread {
                        Log.debug("onLost: $network")
                    }
                }
            }
        }

        // 注册网络回调
        networkCallback.let { callback ->
            val request = NetworkRequest.Builder()
                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .build()

            connectivityManager!!.registerNetworkCallback(request, callback)
        }
    }
}